package io.github.javpower.imagerex.service;

import com.google.common.collect.Lists;
import io.github.javpower.imagerex.mapper.ImageMapper;
import io.github.javpower.imagerex.model.Image;
import io.github.javpower.imagerex.req.ImageReq;
import io.github.javpower.imagerex.res.PageResult;
import io.github.javpower.imagerex.util.PaginationUtil;
import io.github.javpower.vectorexbootstater.builder.LambdaQueryWrapper;
import io.github.javpower.vectorexbootstater.core.VectoRexResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.zip.ZipEntry;

@Service
@Slf4j
public class VectorExService {
    private final ImageMapper imageMapper;
    private final FeatureExtractor featureExtractor;

    public VectorExService(FeatureExtractor featureExtractor, ImageMapper imageMapper) {
        this.featureExtractor = featureExtractor;
        this.imageMapper = imageMapper;
    }

    public String deleteImageByName(String name) {
        try {
            // 调用服务删除指定名称的图片实体
            boolean deleted = del(name);
            if (deleted) {
                return "Image with name '" + name + "' deleted successfully!";
            } else {
                return "Image with name '" + name + "' not found!";
            }
        } catch (Exception e) {
            return "Error deleting the image: " + e.getMessage();
        }
    }

    public String uploadSingleImage(MultipartFile file) {
        if (!isImage(file.getContentType())) {
            throw new IllegalArgumentException("Only image files are allowed!");
        }
        try {
            // 创建临时文件
            File tempFile = File.createTempFile("temp", null);
            file.transferTo(tempFile);
            // 提取特征向量
            List<Float> vector;
            try {
                vector = featureExtractor.getVectorFeatures(tempFile.getAbsolutePath());
            }catch (Exception e){
                log.error(file.getOriginalFilename()+" extract vector error",e);
                throw new RuntimeException(e);
            }
            // 将图片转换为base64编码
            String base64Image = encodeFileToBase64Binary(tempFile.getAbsolutePath());
            // 创建Image实体类实例
            Image image = new Image(file.getOriginalFilename(), base64Image, vector);
            // 保存到数据库或向量数据库
            saveImages(Lists.newArrayList(image));
            // 删除临时文件
            tempFile.delete();
            return "Image processed successfully!";
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public String uploadZipFile(MultipartFile file) {
        if (!file.getContentType().equals("application/zip")) {
            throw new IllegalArgumentException("Only zip files are allowed!");
        }
        List<Image> images = new ArrayList<>();
        try (InputStream is = file.getInputStream();
             ZipArchiveInputStream zis = new ZipArchiveInputStream(
                     new BufferedInputStream(is), "UTF-8")) {
            ZipEntry entry;
            while ((entry = zis.getNextZipEntry()) != null) {
                if (!entry.isDirectory() && isImage(entry.getName())) {
                    File tempFile = File.createTempFile("temp", null);
                    try (OutputStream os = FileUtils.openOutputStream(tempFile)) {
                        IOUtils.copy(zis, os);
                    }
                    List<Float> vector;
                    try {
                        vector = featureExtractor.getVectorFeatures(tempFile.getAbsolutePath());
                    }catch (Exception e){
                        log.error(entry.getName()+" extract vector error",e);
                        continue;
                    }
                    String base64Image = encodeFileToBase64Binary(tempFile.getAbsolutePath());
                    images.add(new Image(entry.getName(), base64Image, vector));
                    tempFile.delete(); // 删除临时文件
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 批量保存Image实体到数据库或向量数据库
        saveImages(images);

        return "Zip file processed successfully!";
    }

    private boolean isImage(String fileName) {
        return fileName.contains("jpg") || fileName.contains("jpeg") || fileName.contains("png") || fileName.contains("gif");
    }

    private String encodeFileToBase64Binary(String fileName) throws IOException {
        File file = new File(fileName);
        FileInputStream fileInputStreamReader = new FileInputStream(file);
        byte[] bytes = new byte[(int) file.length()];
        fileInputStreamReader.read(bytes);
        return Base64.getEncoder().encodeToString(bytes);
    }
    private void saveImages(List<Image> images) {
        imageMapper.insert(images);
    }
    private boolean del(String name) {
        imageMapper.removeById(name);
        return true;
    }

    public PageResult<Image> page(ImageReq req) {
        LambdaQueryWrapper<Image> queryWrapper = imageMapper.queryWrapper();
        if(req.getName()!=null){
            queryWrapper.like(Image::getName,req.getName());
        }
        List<VectoRexResult<Image>> query = queryWrapper.query();
        if(query!=null){
            List<Image> images = new ArrayList<>();
            for (VectoRexResult<Image> imageVectoRexResult : query) {
                images.add(imageVectoRexResult.getEntity());
            }
            return PaginationUtil.paginate(images,req.getPageIndex(),req.getPageSize());
        }
        return null ;
    }

    public List<VectoRexResult<Image>> search(MultipartFile file, Integer topK) {
        if (!isImage(file.getContentType())) {
            throw new IllegalArgumentException("Only image files are allowed!");
        }
        try {
            // 创建临时文件
            File tempFile = File.createTempFile("temp", null);
            file.transferTo(tempFile);
            // 提取特征向量
            List<Float> vector = featureExtractor.getVectorFeatures(tempFile.getAbsolutePath());
            List<VectoRexResult<Image>> query = imageMapper.queryWrapper().vector(Image::getVector, vector).topK(topK).query();
            // 删除临时文件
            tempFile.delete();
            return query;

        } catch (IOException e) {
            throw new RuntimeException("Error processing the image file: " + e.getMessage());
        }
    }

}
